/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package AccesoDatos.Persistencia.Manager;

import AccesoDatos.Persistencia.Entidad.EDocente;
import AccesoDatos.Persistencia.Entidad.EEstudiante;
import AccesoDatos.Persistencia.Entidad.EUsuario;
import LogicaNegocio.Usuarios.Docente;
import LogicaNegocio.Usuarios.Estudiante;
import LogicaNegocio.Usuarios.Usuario;
import MainBiblioSoft.BiblioSoft;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.persistence.RollbackException;

/**
 * Esta clase en java es el gestor de persistencia
 * de objetos Usuario en la base de datos BiblioSoft.
 *
 * @author sebaxtian
 * Archivo: ManagerUsuario.java
 * @version 1.0
 * Fecha: lun may  3 02:14:04 COT 2010
 */


public class ManagerUsuario {

    @PersistenceUnit
    private EntityManagerFactory managerFactory;
    private EntityManager entityManager;

    /**
     * Metodo constructor, crea un gestor para la persistencia de Usuario
     * 
     */
    public ManagerUsuario() {
        managerFactory = BiblioSoft.managerFactory;
        entityManager = managerFactory.createEntityManager();
    }

    /**
     * Este metodo se encarga de la persistencia en la entidad Usuario
     * de un objeto Usuario.
     *
     * @param usuario
     */
    public void crearUsuario(Usuario usuario) throws RollbackException, EntityExistsException {
        entityManager.clear();
        EUsuario entidadUsuario = new EUsuario();
        entidadUsuario.setIdentificacionusuario(usuario.getIdentificacionUsuario());
        entidadUsuario.setPrimerapellido(usuario.getPrimerApellido());
        entidadUsuario.setSegundoapellido(usuario.getSegundoApellido());
        entidadUsuario.setPrimernombre(usuario.getPrimerNombre());
        entidadUsuario.setSegundonombre(usuario.getSegundoNombre());
        entidadUsuario.setDireccion(usuario.getDireccion());
        entidadUsuario.setTelefono(usuario.getTelefono());
        entidadUsuario.setEmail(usuario.getEmail());
        entidadUsuario.setActivo(usuario.getActivo());
        EntityTransaction transaccion = entityManager.getTransaction();
        try{
        transaccion.begin();
        entityManager.persist(entidadUsuario);
        } catch (EntityExistsException ex) {
            throw ex;
        } finally {
            transaccion.commit();
        }
        entityManager.clear();
        if(usuario.getClass() == Estudiante.class){
            Estudiante estudiante = (Estudiante)usuario;
            crearEstudiante(estudiante);
        }
        if(usuario.getClass() == Docente.class){
            Docente docente = (Docente)usuario;
            crearDocente(docente);
        }
    }

    /**
     * Este metodo se encarga de desactivar el registro de un
     * usuario, tanto estudiante como docente.
     *
     * @param identificacionUsuario
     */
    public void desactivarUsuario(int identificacionUsuario) {
        entityManager.clear();
        EUsuario entidadUsuario;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadUsuario = entityManager.find(EUsuario.class, identificacionUsuario);
        transaccion.commit();
        if(entidadUsuario != null){
            entidadUsuario.setActivo(false);
            transaccion.begin();
            entityManager.merge(entidadUsuario);
            transaccion.commit();
            //desactiva el usuario en la entidad Estudiante ó Docente
            desactivarEstudiante(identificacionUsuario);
            desactivarDocente(identificacionUsuario);
        }
        entityManager.clear();
    }

    public void actualizarUsuario(int identificacionUsuario, Usuario usuario) {
        entityManager.clear();
        EUsuario entidadUsuario;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadUsuario = entityManager.find(EUsuario.class, identificacionUsuario);
        transaccion.commit();
        if(entidadUsuario != null){
            entidadUsuario.setIdentificacionusuario(usuario.getIdentificacionUsuario());
            entidadUsuario.setPrimerapellido(usuario.getPrimerApellido());
            entidadUsuario.setSegundoapellido(usuario.getSegundoApellido());
            entidadUsuario.setPrimernombre(usuario.getPrimerNombre());
            entidadUsuario.setSegundonombre(usuario.getSegundoNombre());
            entidadUsuario.setDireccion(usuario.getDireccion());
            entidadUsuario.setTelefono(usuario.getTelefono());
            entidadUsuario.setEmail(usuario.getEmail());
            transaccion.begin();
            entityManager.merge(entidadUsuario);
            transaccion.commit();
            //actualiza el campo cedula en ordenes y multas para Usuarios
            Query consulta = entityManager.createQuery("UPDATE EOrden e SET e.identificacionusuario = :identificacionusuarionuevo WHERE e.identificacionusuario = :identificacionusuarioanterior");
            consulta.setParameter("identificacionusuarionuevo", usuario.getIdentificacionUsuario());
            consulta.setParameter("identificacionusuarioanterior", identificacionUsuario);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
            consulta = entityManager.createQuery("UPDATE EMulta e SET e.identificacionusuario = :identificacionusuarionuevo WHERE e.identificacionusuario = :identificacionusuarioanterior");
            consulta.setParameter("identificacionusuarionuevo", usuario.getIdentificacionUsuario());
            consulta.setParameter("identificacionusuarioanterior", identificacionUsuario);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
            //actualiza el usuario en la entidad Estudiante ó Docente
            if(usuario.getClass() == Estudiante.class){
                Estudiante estudiante = (Estudiante)usuario;
                actualizarEstudiante(identificacionUsuario, estudiante);
            }
            if(usuario.getClass() == Docente.class){
                Docente docente = (Docente)usuario;
                actualizarDocente(identificacionUsuario, docente);
            }
        }
        entityManager.clear();
    }

    /**
     * Obtiene un usuario de la entidad usuario.
     *
     * @param identificacionUsuario
     * @return usuario
     */
    public Usuario obtenerUsuario(int identificacionUsuario) throws Exception {
        entityManager.clear();
        EUsuario entidadUsuario;
        Usuario usuario = null;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadUsuario = entityManager.find(EUsuario.class, identificacionUsuario);
        transaccion.commit();
        if(entidadUsuario != null){
            usuario = new Usuario();
            usuario.setIdentificacionUsuario(entidadUsuario.getIdentificacionusuario());
            usuario.setPrimerApellido(entidadUsuario.getPrimerapellido());
            usuario.setPrimerNombre(entidadUsuario.getPrimernombre());
            usuario.setSegundoApellido(entidadUsuario.getSegundoapellido());
            usuario.setSegundoNombre(entidadUsuario.getSegundonombre());
            usuario.setDireccion(entidadUsuario.getDireccion());
            usuario.setTelefono(entidadUsuario.getTelefono());
            usuario.setEmail(entidadUsuario.getEmail());
            usuario.setActivo(entidadUsuario.getActivo());
        }else {
            throw new Exception("El Usuario con cedula : "+identificacionUsuario+" no esta registrado en el sistema");
        }
        entityManager.clear();
        return usuario;
    }

    /**
     * Este metodo se encarga de la persistencia en la entidad Estudiante
     * de un objeto Estudiante.
     *
     * @param estudiante
     */
    private void crearEstudiante(Estudiante estudiante) {
        entityManager.clear();
        EEstudiante entidadEstudiante = new EEstudiante();
        entidadEstudiante.setIdentificacionusuario(estudiante.getIdentificacionUsuario());
        entidadEstudiante.setPrimerapellido(estudiante.getPrimerApellido());
        entidadEstudiante.setSegundoapellido(estudiante.getSegundoApellido());
        entidadEstudiante.setPrimernombre(estudiante.getPrimerNombre());
        entidadEstudiante.setSegundonombre(estudiante.getSegundoNombre());
        entidadEstudiante.setDireccion(estudiante.getDireccion());
        entidadEstudiante.setTelefono(estudiante.getTelefono());
        entidadEstudiante.setEmail(estudiante.getEmail());
        entidadEstudiante.setActivo(estudiante.getActivo());
        entidadEstudiante.setUniversidad(estudiante.getUniversidad());
        entidadEstudiante.setCarrera(estudiante.getCarrera());
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entityManager.persist(entidadEstudiante);
        transaccion.commit();
        entityManager.clear();
    }

    /**
     * Desactica el registro de un estudiante en la base de datos.
     *
     * @param identificacionUsuario
     */
    private void desactivarEstudiante(int identificacionUsuario) {
        entityManager.clear();
        EEstudiante entidadEstudiante;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadEstudiante = entityManager.find(EEstudiante.class, identificacionUsuario);
        transaccion.commit();
        if(entidadEstudiante != null){
            entidadEstudiante.setActivo(false);
            transaccion.begin();
            entityManager.merge(entidadEstudiante);
            transaccion.commit();
        }
        entityManager.clear();
    }

    /**
     * Metodo que actualiza un estudiante de la base de datos.
     *
     * @param identificacionUsuario
     * @param estudiante
     */
    private void actualizarEstudiante(int identificacionUsuario, Estudiante estudiante) {
        entityManager.clear();
        EEstudiante entidadEstudiante;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadEstudiante = entityManager.find(EEstudiante.class, identificacionUsuario);
        transaccion.commit();
        if(entidadEstudiante != null){
            entidadEstudiante.setIdentificacionusuario(estudiante.getIdentificacionUsuario());
            entidadEstudiante.setPrimerapellido(estudiante.getPrimerApellido());
            entidadEstudiante.setSegundoapellido(estudiante.getSegundoApellido());
            entidadEstudiante.setPrimernombre(estudiante.getPrimerNombre());
            entidadEstudiante.setSegundonombre(estudiante.getSegundoNombre());
            entidadEstudiante.setDireccion(estudiante.getDireccion());
            entidadEstudiante.setTelefono(estudiante.getTelefono());
            entidadEstudiante.setEmail(estudiante.getEmail());
            entidadEstudiante.setActivo(estudiante.getActivo());
            entidadEstudiante.setUniversidad(estudiante.getUniversidad());
            entidadEstudiante.setCarrera(estudiante.getCarrera());
            transaccion.begin();
            entityManager.merge(entidadEstudiante);
            transaccion.commit();
        }
        entityManager.clear();
    }

    /**
     * Obtiene un estudiante identificado de la base de datos.
     *
     * @param identificacionUsuario
     * @return estudiante
     */
    public Estudiante obtenerEstudiante(int identificacionUsuario) {
        entityManager.clear();
        EEstudiante entidadEstudiante;
        Estudiante estudiante = null;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadEstudiante = entityManager.find(EEstudiante.class, identificacionUsuario);
        transaccion.commit();
        if(entidadEstudiante != null){
            estudiante = new Estudiante();
            estudiante.setIdentificacionUsuario(entidadEstudiante.getIdentificacionusuario());
            estudiante.setPrimerApellido(entidadEstudiante.getPrimerapellido());
            estudiante.setSegundoApellido(entidadEstudiante.getSegundoapellido());
            estudiante.setPrimerNombre(entidadEstudiante.getPrimernombre());
            estudiante.setSegundoNombre(entidadEstudiante.getSegundonombre());
            estudiante.setDireccion(entidadEstudiante.getDireccion());
            estudiante.setTelefono(entidadEstudiante.getTelefono());
            estudiante.setEmail(entidadEstudiante.getEmail());
            estudiante.setActivo(entidadEstudiante.getActivo());
            estudiante.setUniversidad(entidadEstudiante.getUniversidad());
            estudiante.setCarrera(entidadEstudiante.getCarrera());
        }
        entityManager.clear();
        return estudiante;
    }

    /**
     * Este metodo se encarga de crear un docente en la
     * entidad Docente.
     *
     * @param docente
     */
    private void crearDocente(Docente docente) {
        entityManager.clear();
        EDocente entidadDocente = new EDocente();
        entidadDocente.setIdentificacionusuario(docente.getIdentificacionUsuario());
        entidadDocente.setPrimerapellido(docente.getPrimerApellido());
        entidadDocente.setSegundoapellido(docente.getSegundoApellido());
        entidadDocente.setPrimernombre(docente.getPrimerNombre());
        entidadDocente.setSegundonombre(docente.getSegundoNombre());
        entidadDocente.setDireccion(docente.getDireccion());
        entidadDocente.setTelefono(docente.getTelefono());
        entidadDocente.setEmail(docente.getEmail());
        entidadDocente.setActivo(docente.getActivo());
        entidadDocente.setDependencia(docente.getDependecia());
        entidadDocente.setTitulo(docente.getTitulo());
        entidadDocente.setAreasinteres(docente.getAreasInteres());
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entityManager.persist(entidadDocente);
        transaccion.commit();
        entityManager.clear();
    }

    /**
     * Desactica el registro de un docente en la base de datos.
     *
     * @param identificacionUsuario
     */
    private void desactivarDocente(int identificacionUsuario) {
        entityManager.clear();
        EDocente entidadDocente;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadDocente = entityManager.find(EDocente.class, identificacionUsuario);
        transaccion.commit();
        if(entidadDocente != null){
            entidadDocente.setActivo(false);
            transaccion.begin();
            entityManager.merge(entidadDocente);
            transaccion.commit();
        }
        entityManager.clear();
    }

    /**
     * Metodo que actualiza un estudiante de la base de datos.
     * 
     * @param identificacionUsuario
     * @param docente
     */
    private void actualizarDocente(int identificacionUsuario, Docente docente) {
        entityManager.clear();
        EDocente entidadDocente;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadDocente = entityManager.find(EDocente.class, identificacionUsuario);
        transaccion.commit();
        if(entidadDocente != null){
            entidadDocente.setIdentificacionusuario(docente.getIdentificacionUsuario());
            entidadDocente.setPrimerapellido(docente.getPrimerApellido());
            entidadDocente.setSegundoapellido(docente.getSegundoApellido());
            entidadDocente.setPrimernombre(docente.getPrimerNombre());
            entidadDocente.setSegundonombre(docente.getSegundoNombre());
            entidadDocente.setDireccion(docente.getDireccion());
            entidadDocente.setTelefono(docente.getTelefono());
            entidadDocente.setEmail(docente.getEmail());
            entidadDocente.setActivo(docente.getActivo());
            entidadDocente.setDependencia(docente.getDependecia());
            entidadDocente.setTitulo(docente.getTitulo());
            entidadDocente.setAreasinteres(docente.getAreasInteres());
            transaccion.begin();
            entityManager.merge(entidadDocente);
            transaccion.commit();
            //actualiza la cedula en la entidad recomendaciones
            Query consulta = entityManager.createQuery("UPDATE ERecomendacion e SET e.identificacionusuario = :identificacionusuarionuevo WHERE e.identificacionusuario = :identificacionusuarioanterior");
            consulta.setParameter("identificacionusuarionuevo", docente.getIdentificacionUsuario());
            consulta.setParameter("identificacionusuarioanterior", identificacionUsuario);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
        }
        entityManager.clear();
    }

    public Docente obtenerDocente(int identificacionUsuario) {
        entityManager.clear();
        EDocente entidadDocente;
        Docente docente = null;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadDocente = entityManager.find(EDocente.class, identificacionUsuario);
        transaccion.commit();
        if(entidadDocente != null){
            docente = new Docente();
            docente.setIdentificacionUsuario(entidadDocente.getIdentificacionusuario());
            docente.setPrimerApellido(entidadDocente.getPrimerapellido());
            docente.setSegundoApellido(entidadDocente.getSegundoapellido());
            docente.setPrimerNombre(entidadDocente.getPrimernombre());
            docente.setSegundoNombre(entidadDocente.getSegundonombre());
            docente.setDireccion(entidadDocente.getDireccion());
            docente.setTelefono(entidadDocente.getTelefono());
            docente.setEmail(entidadDocente.getEmail());
            docente.setActivo(entidadDocente.getActivo());
            docente.setDependencia(entidadDocente.getDependencia());
            docente.setTitulo(entidadDocente.getTitulo());
            docente.setAreasInteres(entidadDocente.getAreasinteres());
        }
        entityManager.clear();
        return docente;
    }
}
